// Quad3D.cpp: implementation of the CQuad3D class.
//
//////////////////////////////////////////////////////////////////////
#include "../common.h"
#include "Quad3D.h"
#include "../VMain.h"

//////////////////////////////////////////////////////////////////////
int CQuad3D::s_nId = 0;
#ifdef UNDER_CE
static void transform_point(GLfloat out[4], const GLfloat m[16], const GLfloat in[4])
{
#define M(row,col) m[col*4+row]
    out[0] =
        M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
    out[1] =
        M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
    out[2] =
        M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
    out[3] =
        M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
// gluProject source code (说明见OpenGL API文档)
static GLint gluProject(GLfloat objx, GLfloat objy, GLfloat objz,
                        const GLfloat  modelMatrix[16], const GLfloat projMatrix[16],
                        const GLint viewport[4], GLfloat* winx, GLfloat* winy,
                        GLfloat* winz)
{
    // matrice transformation
    GLfloat in[4], out[4];
    //initialize matrice and column vector as a transformer
    in[0] = objx;
    in[1] = objy;
    in[2] = objz;
    in[3] = 1.0;
    transform_point(out, modelMatrix, in);  //乘以模型视图矩阵
    transform_point(in, projMatrix, out);   //乘以投影矩阵

    //齐次向量的第四项不能为0
    if (in[3] == 0.0)
    {
        return GL_FALSE;
    }

    //向量齐次化标准化
    in[0] /= in[3];
    in[1] /= in[3];
    in[2] /= in[3];
    //视口向量的作用
    *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
    *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
    *winz = (1 + in[2]) / 2;
    return GL_TRUE;
}
#endif

//
int CQuad3D::MakeId()
{
    return ++s_nId;
}

// Construction/Destruction
CQuad3D::CQuad3D(int Id, float fWidth, float fHeight, CVector& fPosition, float fAngle, GLuint nIdTexture)
{
    //
    m_nID = Id;
    m_fWidth =  fWidth;
    m_fHeight = fHeight;
    m_fWidthBK = fWidth;
    m_fHeightBK = fHeight;
    m_v3Position = fPosition;
    m_fAngle = fAngle;

    m_nIdTexture = nIdTexture;
    m_bIsPlaying = false;
    m_bClick     = false;
    m_ntop       = 0;
    m_nleft      = 0;
    m_nright     = 0;
    m_nbottom    = 0;
    m_nCenter = OTHER;
    m_nNum   = 0;
}

CQuad3D::~CQuad3D()
{
    m_nID = -1;

}

void CQuad3D::SetAngle(float fAngle)
{
    m_fAngle = fAngle;
}

void CQuad3D::SetId(int Id)
{
    m_nID = Id;
}

void CQuad3D::SetPosition(CVector& rPosition)
{
    m_v3Position = rPosition;
}

void CQuad3D::OffsetPos(CVector& rV3Offset)
{
    m_v3Position += rV3Offset;
}

void CQuad3D::Render()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    float  pfVertices[] =
    {
        -m_fWidth / 2, m_fHeight, 0.0f,
        m_fWidth / 2, m_fHeight, 0.0f,
        m_fWidth / 2, 0, 0.0f,
        m_fWidth / 2, 0, 0.0f,
        -m_fWidth / 2, 0, 0.0f,
        -m_fWidth / 2, m_fHeight, 0.0f
    };

    GLfloat textures[] =
    {
        0.0f, 0.0f,
        1.0f, 0.0f,
        1.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 1.0f,
        0.0f, 0.0f
    };

    glPushMatrix();
    glTranslatef(m_v3Position.x, m_v3Position.y, m_v3Position.z);

    if (m_bClick)
    {
        //画点中状态
        m_fWidth -= 0.1f;
        m_fHeight -= 0.1f;

        m_nNum ++;

        if (m_nNum > 8) //大于8帧
        {
            m_nNum = 0;
            m_bClick = false;
            m_fWidth = m_fWidthBK;
            m_fHeight = m_fHeightBK;
        }
    }

    glRotatef(m_fAngle, 0.0, 1.0, 0.0);
    SetRect();

    glBindTexture(GL_TEXTURE_2D, m_nIdTexture);
    glTexCoordPointer(2, GL_FLOAT, 0, textures);
    glVertexPointer(3, GL_FLOAT, 0, pfVertices);
    glDrawArrays(GL_TRIANGLES, 0, 6);

#if 0

    if (m_enReflect)//画倒影
    {
        float  pfVertices2[] =
        {
            -m_fWidth / 2, 0, 0.0f,
            m_fWidth / 2, 0, 0.0f,
            m_fWidth / 2, -m_fHeight* .5 , 0.0f
        };

        float  pfVertices3[] =
        {
            -m_fWidth / 2, -m_fHeight* .5 , 0.0f,
            m_fWidth / 2, -m_fHeight* .5 , 0.0f,
            -m_fWidth / 2, 0, 0.0f
        };
        GLfloat textures2[] =
        {
            0.0f, 1.0f,
            1.0f, 1.0f,
            1.0f, 0.0f
        };
        GLfloat textures3[] =
        {
            0.0f, 0.0f,
            1.0f, 0.0f,
            0.0f, 1.0f
        };

        GLfloat color2[] =
        {
            0.8f, 0.8f, 0.8f,
            0.8f, 0.8f, 0.8f,
            0.0f, 0.0f, 0.0f
        };

        GLfloat color3[] =
        {
            0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            0.8f, 0.8f, 0.8f
        };
        glEnableClientState(GL_COLOR_ARRAY);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,   GL_ONE);


        glColorPointer(3, GL_FLOAT, 0, color2); //右上三角
        glTexCoordPointer(2, GL_FLOAT, 0, textures2);
        glVertexPointer(3, GL_FLOAT, 0, pfVertices2);
        glColor4f(1.0f, 1.0f, 1.0f, 0.1f);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glColorPointer(3, GL_FLOAT, 0, color3); //左下三角
        glTexCoordPointer(2, GL_FLOAT, 0, textures3);
        glVertexPointer(3, GL_FLOAT, 0,  pfVertices3);


        glDrawArrays(GL_TRIANGLES, 0, 3);

        glDisable(GL_BLEND);
        glDisableClientState(GL_COLOR_ARRAY);
    }

#endif
    glPopMatrix();
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

int CQuad3D::Click(int x, int y)
{
    if (VMain::inRect(m_nleft, m_ntop, m_nright, m_nbottom, x, y))
    {
        m_bClick = true;
        return m_nID;
    }

    return -1;
}

void CQuad3D::SetCenter(int bCenter)
{
    m_nCenter = bCenter;
}

void CQuad3D::SetRect()
{
#ifndef UNDER_CE
    GLdouble x, y, z;
#else
    GLfloat x, y, z;
#endif

#ifndef UNDER_CE
    glGetDoublev(GL_MODELVIEW_MATRIX, m_ModelMatrix);
    glGetDoublev(GL_PROJECTION_MATRIX, m_ProjMatrix);
    glGetIntegerv(GL_VIEWPORT, m_viewport);

    gluProject(0, 0,
               0, m_ModelMatrix,
               m_ProjMatrix, m_viewport,
               &x, &y, &z);
#else
    glGetFloatv(GL_MODELVIEW_MATRIX, m_ModelMatrix);
    glGetFloatv(GL_PROJECTION_MATRIX, m_ProjMatrix);
    glGetIntegerv(GL_VIEWPORT, m_viewport);
    gluProject(0, 0, 0, m_ModelMatrix, m_ProjMatrix, m_viewport, &x, &y, &z);
#endif

    m_winx = (int)x;
    m_winy = m_viewport[3] - (GLint) y - 1 + 260;

    switch (m_nCenter)
    {
    case CENTER:
        m_winy -= 45;
        m_nleft   = m_winx - 120;
        m_ntop    = m_winy - 120;
        m_nright  = m_winx + 120;
        m_nbottom = m_winy + 120;
        break;
    case LEFTSLIDER:
        m_nleft   = m_winx - 87 ;
        m_ntop    = m_winy - 86;
        m_nright  = m_winx - 7 ;
        m_nbottom = m_winy + 86;
        break;
    case RIGHTSLIDER:
        m_nleft   = m_winx + 3 ;
        m_ntop    = m_winy - 73;
        m_nright  = m_winx + 84 ;
        m_nbottom = m_winy + 73;
        break;
    default:
        m_nleft   = m_winx - 80 ;
        m_ntop    = m_winy - 80;
        m_nright  = m_winx + 80 ;
        m_nbottom = m_winy + 80;
        break;
    }

}









